package org.zbclan.bf2.rcon;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;

public class SoundCapture implements SoundRunnable {

	private final Callback callback;

	private Thread thread;
	private TargetDataLine line;

	public SoundCapture(Callback callback) {

		if (callback == null) {
			throw new IllegalArgumentException("callback required");
		}

		this.callback = callback;

		return;
	}

	@Override
	public void run() {

		line.start();

		int bufferLengthInBytes = (line.getBufferSize() / 8) * frameSize;
		byte[] data = new byte[bufferLengthInBytes];
		int numBytesRead;

		while (thread != null) {
			numBytesRead = line.read(data, 0, bufferLengthInBytes);
			callback.captured(data, numBytesRead);

			// if (numBytesRead == -1) {
			// break;
			// }
		}
		// AudioInputStream audioInputStream = new AudioInputStream(line);
		// while (thread != null) {
		// try {
		// numBytesRead = audioInputStream.read(data, 0,
		// bufferLengthInBytes);
		// callback.captured(data, numBytesRead);
		// } catch (IOException ex) {
		// /*
		// * FIXME
		// */
		// }
		// }

		line.stop();

		line.close();

		return;
	}

	public synchronized void start(LineListener listener)
			throws LineUnavailableException {
		if (thread == null) {
			line = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(
					TargetDataLine.class, format));
			line.addLineListener(listener);
			line.open(format, line.getBufferSize());

			thread = new Thread(this, "SoundCapture");
			thread.setDaemon(true);
			thread.start();
		}
	}

	public synchronized void stop() {
		thread = null;
		line.flush();
	}

	public synchronized void pause() {
		if (thread != null) {
			line.stop();
		}
	}

	public void resume() {
		if (thread != null) {
			line.start();
		}
	}

	public interface Callback {

		/**
		 * notifies how many bytes of sound sample captured
		 * 
		 * @param buffer
		 *            contains data
		 * @param size
		 *            number of bytes available in buffer
		 */
		void captured(byte[] buffer, int size);
	}

	public static void main(String[] args) throws IOException,
			LineUnavailableException {

		// Socket socket = new Socket("localhost", 2010);
		// Socket socket = new Socket("192.168.1.2", 2010);
		Socket socket = new Socket("192.168.137.1", 2010);
		final OutputStream out = socket.getOutputStream();

		SoundCapture soundRecorder = new SoundCapture(
				new SoundCapture.Callback() {

					@Override
					public void captured(byte[] data, int size) {
						try {
							out.write(data, 0, size);
						} catch (IOException ex) {
							ex.printStackTrace();
							// echo(ex.toString());
						}
					}
				});
		soundRecorder.start(new LineListener() {

			@Override
			public void update(LineEvent event) {
				System.out.println(event.getType().toString());
			}
		});

		soundRecorder.stop();
		out.close();

		return;
	}
}
